package com.atguigu.web.admin.service.impl;

import com.atguigu.common.exception.LeaseException;
import com.atguigu.common.result.ResultCodeEnum;
import com.atguigu.lease.model.entity.*;
import com.atguigu.model.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.*;
import com.atguigu.web.admin.mapper.*;
import com.atguigu.web.admin.service.*;
import com.atguigu.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.web.admin.vo.fee.FeeValueVo;
import com.atguigu.web.admin.vo.graph.GraphVo;
import com.atguigu.model.entity.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author liubo
 * @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
        implements ApartmentInfoService {
    @Autowired
    private GraphInfoService graphInfoService;
    @Autowired
    private ApartmentFacilityService apartmentFacilityService;
    @Autowired
    private ApartmentLabelService apartmentLabelService;
    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;
    @Autowired
    private ApartmentInfoMapper apartmentInfoMapper;
    @Autowired
    private GraphInfoMapper graphInfoMapper;
    @Autowired
    private LabelInfoMapper labelInfoMapper;
    @Autowired
    private FacilityInfoMapper facilityInfoMapper;
    @Autowired
    private FeeValueMapper feeValueMapper;
    @Autowired
    private RoomInfoMapper roomInfoMapper;
    @Autowired
    private ProvinceInfoService provinceInfoService;
    @Autowired
    private CityInfoService cityInfoService;
    @Autowired
    private DistrictInfoService districtInfoService;

    @Override
    public void customPage(Page<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
        apartmentInfoMapper.customSelectPage(page, queryVo);
    }

    @Override
    public void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {
        boolean isUpdate = apartmentSubmitVo.getId() != null;//判断前端上传的信息列表是否id为空

//        从省市区信息表单根据用户提交的省市区id获取省市区信息
        ProvinceInfo provinceInfo = provinceInfoService.getById(apartmentSubmitVo.getProvinceId());
        CityInfo cityInfo = cityInfoService.getById(apartmentSubmitVo.getCityId());
        DistrictInfo districtInfo = districtInfoService.getById(apartmentSubmitVo.getDistrictId());
//
//        把得到的省市区信息设置给用户提交的表单中
        apartmentSubmitVo.setProvinceName(provinceInfo.getName());
        apartmentSubmitVo.setCityName(cityInfo.getName());
        apartmentSubmitVo.setDistrictName(districtInfo.getName());

//        保存或更新公寓信息
        saveOrUpdate(apartmentSubmitVo);

        if (isUpdate) {
//            如果前端传了公寓信息，先删除旧的公寓相关信息，如图片列、配套列等
            LambdaQueryWrapper<GraphInfo> graphQueryWrapper = new LambdaQueryWrapper<>();
            graphQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT);
            //筛选出 GraphInfo 表中 item_type 字段为 “公寓” 的记录。
            graphQueryWrapper.eq(GraphInfo::getItemId, apartmentSubmitVo.getId());
            //继续用 eq 加条件：给查询再附加一个 “等于” 条件,在之前 “item_type 是公寓” 的基础上，
            // 进一步筛选出 item_id 等于当前公寓 ID 的记录 → 也就是当前公寓之前关联的所有图片记录。
            graphInfoService.remove(graphQueryWrapper);
            //这三行构造好条件后,graphInfoService 会根据 graphQueryWrapper 里的条件，到数据库
            // GraphInfo 表中找到符合条件的记录，然后删除它们。
//            这样就实现了 “更新公寓时，先清空该公寓旧的图片关联” 的需求.

//            2.删除配套列表
            LambdaQueryWrapper<ApartmentFacility> facilityQueryWrapper = new LambdaQueryWrapper<>();
            facilityQueryWrapper.eq(ApartmentFacility::getApartmentId, apartmentSubmitVo.getId());
            apartmentFacilityService.remove(facilityQueryWrapper);

//           3.删除标签列表
            LambdaQueryWrapper<ApartmentLabel> labelQueryWrapper = new LambdaQueryWrapper<>();
            labelQueryWrapper.eq(ApartmentLabel::getApartmentId, apartmentSubmitVo.getId());
            apartmentLabelService.remove(labelQueryWrapper);

//            4.删除杂费列表
            LambdaQueryWrapper<ApartmentFeeValue> feeQueryWrapper = new LambdaQueryWrapper<>();
            feeQueryWrapper.eq(ApartmentFeeValue::getApartmentId, apartmentSubmitVo.getId());
            apartmentFeeValueService.remove(feeQueryWrapper);

//            把用户上传的关于公寓的各类信息插入，这里是插入图片列表
//            先获取用户上传的图片列表，做成list集合
            List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
//            如果图片列表集合不为空，将前端提交的图片信息（GraphVo 列表）转换为数据库实
//            体类（GraphInfo）的列表。并批量插入到数据库中。
            if (!CollectionUtils.isEmpty(graphVoList)) {
                ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
                for (GraphVo graphVo : graphVoList) {//遍历用户传的graphlist
                    GraphInfo graphInfo = new GraphInfo();//新建图片信息对象
                    graphInfo.setItemType(ItemType.APARTMENT);//这是公寓信息的保存所以固定了
//                setItemType为Apartment
                    graphInfo.setItemId(apartmentSubmitVo.getId());//把用户传的vo的id赋值给
//                    graphInfo
                    graphInfo.setName(graphVo.getName());
                    graphInfo.setUrl(graphVo.getUrl());
                    graphInfoList.add(graphInfo);//将转换后的单个图片实体（GraphInfo）添加到
                    // 列表中，为后续批量插入数据库做准备。
                }
                graphInfoService.saveBatch(graphInfoList);
            }

//            2.插入配套列表
            List<Long> facilityInfoIdList = apartmentSubmitVo.getFacilityInfoIds();
            if (!CollectionUtils.isEmpty(facilityInfoIdList)) {
                ArrayList<ApartmentFacility> facilityList = new ArrayList<>();
                for (Long facilityId : facilityInfoIdList) {
                    ApartmentFacility apartmentFacility = new ApartmentFacility();
                    apartmentFacility.setApartmentId(apartmentSubmitVo.getId());
                    apartmentFacility.setFacilityId(facilityId);
                    facilityList.add(apartmentFacility);
                }
                apartmentFacilityService.saveBatch(facilityList);
            }

//            3.插入标签列表
            List<Long> labelIds = apartmentSubmitVo.getLabelIds();
            if (!CollectionUtils.isEmpty(labelIds)) {
                List<ApartmentLabel> apartmentLabelList = new ArrayList<>();
                for (Long labelId : labelIds) {
                    ApartmentLabel apartmentLabel = new ApartmentLabel();
                    apartmentLabel.setApartmentId(apartmentSubmitVo.getId());
                    apartmentLabel.setLabelId(labelId);
                    apartmentLabelList.add(apartmentLabel);
                }
                apartmentLabelService.saveBatch(apartmentLabelList);
            }

//            4.插入杂费列表
            List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
            if (!CollectionUtils.isEmpty(feeValueIds)) {
                ArrayList<ApartmentFeeValue> apartmentFeeValueList = new ArrayList<>();
                for (Long feeValueId : feeValueIds) {
                    ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                    apartmentFeeValue.setApartmentId(apartmentSubmitVo.getId());
                    apartmentFeeValue.setFeeValueId(feeValueId);
                    apartmentFeeValueList.add(apartmentFeeValue);
                }
                apartmentFeeValueService.saveBatch(apartmentFeeValueList);
            }
        }
    }

    @Override
    public ApartmentDetailVo getApartmentDetailById(Long id) {
//        实现Service接口中查询公寓详细信息的抽象方法，：根据公寓 ID 查询
//        并组装 公寓详情页所需的所有数据，返回一个包含完整信息的
//        ApartmentDetailVo 对象

//        1.查询Apartmentinfo
        ApartmentInfo apartmentInfo = this.getById(id);//这里this指当前类ApartmentInfoServiceImpl
//        的实例，因为继承了ServiceImpl所以具备 ServiceImpl 类提供的方法getById，getById() 方法会自动根据
//        主键 ID 查询数据库并返回对象。由于ApartmentServiceImpl 继承了 ServiceImpl<ApartmentInfoMapper
//        , ApartmentInfo>，调用 this.getById(id) 时，MyBatis-Plus 会根据泛型 T（即 ApartmentInfo）
//        自动推断返回值类型（即ApartmentInfo）。
        if (apartmentInfo == null){
            return null;
        }

//        2.查询GraphInfo
        List<GraphVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT,id);

//        3.查询LabelInfo
        List<LabelInfo> labelInfoList = labelInfoMapper.selectListByApartmentId(id);

//        4.查询facilityInfo
        List<FacilityInfo> facilityInfo = facilityInfoMapper.selectListByApartmentId(id);

//        5.查询Feevalue
        List<FeeValueVo> feeValueVoList = feeValueMapper.selectListByApartmentId(id);

//        创建新的ApartmentDetailVo对象，方便把查到的数据绑定到对象里，返给前端
        ApartmentDetailVo adminApartmentDetailVo = new ApartmentDetailVo();
        BeanUtils.copyProperties(apartmentInfo,adminApartmentDetailVo);
        adminApartmentDetailVo.setGraphVoList(graphVoList);
        adminApartmentDetailVo.setLabelInfoList(labelInfoList);
        adminApartmentDetailVo.setFacilityInfoList(facilityInfo);
        adminApartmentDetailVo.setFeeValueVoList(feeValueVoList);
        return adminApartmentDetailVo;
    }

    @Override
    public void removeApartmentById(Long id) {
        LambdaQueryWrapper<RoomInfo> roomQueryWrapper = new LambdaQueryWrapper<>();
        roomQueryWrapper.eq(RoomInfo::getApartmentId,id);
        Long count = roomInfoMapper.selectCount(roomQueryWrapper);
        if (count>0) {
            throw new LeaseException(ResultCodeEnum.DELETE_ERROR);
        }



//        1.删除GraphInfo
            LambdaQueryWrapper<GraphInfo> graphQueryWrapper = new LambdaQueryWrapper<>();
            graphQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT);
            graphQueryWrapper.eq(GraphInfo::getItemId, id);
            //继续用 eq 加条件：给查询再附加一个 “等于” 条件,在之前 “item_type 是公寓” 的基础上，
            // 进一步筛选出 item_id 等于当前公寓 ID 的记录 → 也就是当前公寓之前关联的所有图片记录。
            graphInfoService.remove(graphQueryWrapper);
            //这三行构造好条件后,graphInfoService 会根据 graphQueryWrapper 里的条件，到数据库
            // GraphInfo 表中找到符合条件的记录，然后删除它们。
//            这样就实现了 “更新公寓时，先清空该公寓旧的图片关联” 的需求.

//            2.删除配套列表
            LambdaQueryWrapper<ApartmentFacility> facilityQueryWrapper = new LambdaQueryWrapper<>();
            facilityQueryWrapper.eq(ApartmentFacility::getApartmentId, id);
            apartmentFacilityService.remove(facilityQueryWrapper);

//           3.删除标签列表
            LambdaQueryWrapper<ApartmentLabel> labelQueryWrapper = new LambdaQueryWrapper<>();
            labelQueryWrapper.eq(ApartmentLabel::getApartmentId, id);
            apartmentLabelService.remove(labelQueryWrapper);

//            4.删除杂费列表
            LambdaQueryWrapper<ApartmentFeeValue> feeQueryWrapper = new LambdaQueryWrapper<>();
            feeQueryWrapper.eq(ApartmentFeeValue::getApartmentId, id);
            apartmentFeeValueService.remove(feeQueryWrapper);

        super.removeById(id);
        }
    }






